package com.mata.worktime.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.mata.worktime.configuration.dingtalk.AppConfig;
import com.mata.worktime.dto.Scheduler1DTO;
import com.mata.worktime.dto.WeekDTO;
import com.mata.worktime.dto.dingtalk.ServiceResult;
import com.mata.worktime.entity.work.Member;
import com.mata.worktime.entity.work.Project;
import com.mata.worktime.entity.work.WorkHour;
import com.mata.worktime.service.TokenService;
import com.mata.worktime.service.scheduler.Scheduler1Service;
import com.mata.worktime.service.work.MemberService;
import com.mata.worktime.service.work.ProjectService;
import com.mata.worktime.service.work.WorkHourService;
import com.mata.worktime.util.WeekUtils;
import com.mata.worktime.vo.scheduler.Scheduler1VO;
import com.taobao.api.ApiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import static com.mata.worktime.configuration.dingtalk.UrlConstant.*;

/**
 * @author wanlili
 * @Desc 定时任务
 */
@Component
public class ScheduledTasks {
    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private TokenService tokenService;
    @Autowired
    private ProjectService projectService;

    @Autowired
    private Scheduler1Service scheduler1Service;

    @Autowired
    private MemberService memberService;

    @Autowired
    private WorkHourService workHourService;

    /**
     * 每周5 下午14点整  提醒项目内成员填报工时
     */
    @Scheduled(cron = "0 0 14 ? * 5")
    public void scheduler1() throws ApiException {

        WeekDTO weekDays = WeekUtils.getWeekDays(0);
        // 获取当前时间
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 1、获取未结束的项目
        List<Project> projectList = projectService.list(new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0")
                .ge("end_date", date));
        for (Project project : projectList) {
            // 存储项目成员ID
            List<String> userIdList = new ArrayList<>();
            userIdList.add(project.getManager());
            // 获取项目的成员
            List<Member> memberList = memberService.list(new QueryWrapper<Member>()
                    .eq("pro_id", project.getId())
                    .select("user_id", "user_name", "pro_id", "join_time"));
            memberList.forEach(member -> userIdList.add(member.getUserId()));
            Scheduler1DTO scheduler1DTO = new Scheduler1DTO();
            scheduler1DTO.setStartDate(weekDays.getStartDate());
            scheduler1DTO.setEndDate(weekDays.getEndDate());
            scheduler1DTO.setProjectId(project.getId());
            scheduler1DTO.setUserIdList(userIdList);
            List<Scheduler1VO> scheduler1VOs = scheduler1Service.getScheduler1VO(scheduler1DTO);
            userIdList.clear();
            System.out.println(scheduler1VOs.toString());
            scheduler1VOs.forEach(scheduler1VO -> userIdList.add(scheduler1VO.getUserId()));
            // 判断已经填报工时的员工  本周是否填满五条，若未满五条，则发送钉钉工作消息
            for (Scheduler1VO scheduler1VO : scheduler1VOs) {
                if (scheduler1VO.getTotal() < 5) {
                    sendMessage(scheduler1VO.getUserId(),
                            "填报提醒： "+scheduler1VO.getUserName()+", 您在项目：" + scheduler1VO.getProjectName() + "    本周还有  " + (5 - scheduler1VO.getTotal()) + "  天工时未上报",
                            "填报提醒");
                }
            }
            // 判断 项目经理 本周 是否填报工时，若未填报，则提醒填报工时
            if (!userIdList.contains(project.getManager())) {
                sendMessage(project.getManager(),
                        "填报提醒： "+ project.getManagerName()+"，您在项目：" +project.getProjectName() + "  本周还未上报报工时信息",
                        "填报提醒");
            }
            for (Member member : memberList) {
                // 判断该项目成员是否本周是否填报工时，若未填报，则发送钉钉工作消息提醒填报
                if (!userIdList.contains(member.getUserId())) {
                    sendMessage(member.getUserId(),
                            "填报提醒： "+member.getUserName()+", 您在项目：" + project.getProjectName() + "  本周还未上报工时信息",
                            "填报提醒");
                }
            }
        }
    }


    /**
     * 每周5 下午17点整  提醒项目经理审核工时
     */
    @Scheduled(cron = "0 0 17 ? * 5")
    public void scheduler2() throws ApiException {

        WeekDTO weekDays = WeekUtils.getWeekDays(0);
        // 获取当前时间
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 1、获取未结束的项目
        List<Project> projectList = projectService.list(new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0")
                .ge("end_date", date));
        for (Project project : projectList) {
            //获取未审核的工时总数
            int count = workHourService.count(new QueryWrapper<WorkHour>()
                    .eq("del_flag", "0")
                    .ne("review_flag", "1")
                    .eq("project_id", project.getId())
                    .between("work_date", weekDays.getStartDate(), weekDays.getEndDate()));
            // 如果 存在未审核的消息，则提醒项目经理去审核
            if (count > 0) {
                sendMessage(project.getManager(),
                        "审核提醒： "+project.getManagerName() +" ,您所管理的项目 " + project.getProjectName() + " ，本周还有  " + count + "  条员工工时未审核",
                        "审核提醒");
            }
        }
    }

    /*
     * 调用钉钉api 向用户发送工作消息
     * @params userId 用户id
     * @params text 消息内容
     * @params title 消息标题
     * @Author CamphorWood
     * */
    public void sendMessage(String userId, String text, String title) throws ApiException {
        String accessToken;

        // 获取accessToken
        ServiceResult<String> accessTokenSr = tokenService.getAccessToken();
        if (!accessTokenSr.isSuccess()) {
            log.info(String.valueOf(ServiceResult.failure(accessTokenSr.getCode(), accessTokenSr.getMessage())));
        }
        accessToken = accessTokenSr.getResult();
        DingTalkClient client = new DefaultDingTalkClient(URL_SEND_WORKMESSAGE);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(Long.parseLong(appConfig.getAgentId()));
        request.setUseridList(userId);
        request.setToAllUser(false);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("markdown");
        msg.setMarkdown(new OapiMessageCorpconversationAsyncsendV2Request.Markdown());
        msg.getMarkdown().setText("#####  " + text);
        msg.getMarkdown().setTitle(title);
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, accessToken);
        log.info(String.valueOf(rsp.getBody()));
    }
}